package avicit.bdp.dgs.mdm.service;

import avicit.bdp.common.datasource.BaseDataSource;
import avicit.bdp.common.utils.database.adapter.DbAdapter;
import avicit.bdp.dgs.mdm.dto.CodeDTO;
import avicit.bdp.dgs.mdm.dto.ColumnDTO;
import avicit.bdp.dgs.mdm.dto.DataDTO;
import avicit.bdp.dgs.mdm.dto.TableDTO;
import avicit.bdp.dgs.mdm.utils.constants.Constants;
import avicit.bdp.dgs.mdm.utils.enums.DataState;
import avicit.bdp.dgs.mdm.utils.enums.OperType;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.BusinessException;
import com.alibaba.fastjson2.JSON;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @金航数码科技有限责任公司
 * @作者：developer
 * @邮箱：developer@avic-digital.com
 * @创建时间： 2023-12-11
 * @类说明：DataManageService
 * @修改记录：
 * @注意事项：
 * @主要功能：数据维护Service
 */
@Service
public class DataManageService {
    private static final Logger logger = LoggerFactory.getLogger(DataManageService.class);

    @Autowired
    private CommonService commonService;

    @Autowired
    private DataCodeService dataCodeService;

    @Autowired
    private ConvertColumnClient convertColumnClient;

    @Autowired
    private MdmLogService mdmLogService;
    @Autowired
    private MdataChangeService mdataChangeService;

    /**
     * 新增数据
     *
     * @param dataDTO
     * @return
     */
    @Transactional
    public String addData(DataDTO dataDTO) {
        if (dataDTO == null) {
            throw new BusinessException("参数为空");
        }
        if (StringUtils.isEmpty(dataDTO.getTableId())) {
            throw new BusinessException("模型Id为空");
        }
        if (dataDTO.getDataMap() == null || dataDTO.getDataMap().size() <= 0) {
            logger.warn("数据为空");
            return null;
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableById(dataDTO.getTableId());
        if (tableDTO == null) {
            throw new BusinessException("未找到模型，新增数据失败,tableId:" + dataDTO.getTableId());
        }

        // 获取字段列表(不包括业务字段)
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(dataDTO.getTableId());
        if (CollectionUtils.isEmpty(columnList)) {
            throw new BusinessException("未找到字段列表，新增数据失败,tableId:" + dataDTO.getTableId());
        }

        // 插入数据
        return addDataInner(dataDTO, tableDTO, columnList);
    }

    /**
     * 删除/批量删除数据，多个id使用英文逗号隔开
     *
     * @param topicId
     * @param id
     * @return
     */
    @Transactional
    public int deleteData(String topicId, String id) {
        if (StringUtils.isBlank(id)) {
            logger.debug("待删除数据ID为空");
            return 0;
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableByTopicId(topicId);

        // 批量删除
        List<String> dataIdList = Arrays.asList(id.trim().split(Constants.COMMA));
        for (String dataId : dataIdList) {
            String sql = this.commonService.getDeleteTableSql(tableDTO.getTableName(), dataId);
            this.commonService.deleteData(tableDTO.getTableName(), sql);
            this.mdmLogService.deleteLog(dataId);

            // 向推送模块保存变更的主数据
            saveChangeData(tableDTO.getId(), dataId, OperType.DELETE.getCode());
        }

        return dataIdList.size();
    }

    /**
     * 修改数据
     *
     * @param dataDTO
     * @return
     */
    @Transactional
    public boolean updateData(DataDTO dataDTO) {
        if (dataDTO == null) {
            throw new BusinessException("参数为空");
        }
        if (StringUtils.isEmpty(dataDTO.getTableId())) {
            throw new BusinessException("模型Id为空");
        }
        if (StringUtils.isEmpty(dataDTO.getDataId())) {
            throw new BusinessException("数据Id为空");
        }
        if (dataDTO.getDataMap() == null || dataDTO.getDataMap().size() <= 0) {
            logger.warn("数据为空");
            return false;
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableById(dataDTO.getTableId());
        if (tableDTO == null) {
            throw new BusinessException("未找到模型，新增数据失败,tableId:" + dataDTO.getTableId());
        }

        // 获取字段列表(不包括业务字段)
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(dataDTO.getTableId());
        if (CollectionUtils.isEmpty(columnList)) {
            throw new BusinessException("未找到字段列表，新增数据失败,tableId:" + dataDTO.getTableId());
        }

        // 更新数据
        return updateDataInner(dataDTO, tableDTO, columnList);
    }

    /**
     * 查询数据详情
     *
     * @param tableId 模型ID
     * @param dataId  数据ID
     * @return
     */
    public Map<String, Object> getDataDetail(String tableId, String dataId) {
        if (StringUtils.isEmpty(tableId)) {
            logger.error("模型Id为空");
            return null;
        }
        if (StringUtils.isEmpty(dataId)) {
            logger.error("数据Id为空");
            return null;
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableById(tableId);

        // 获取字段列表
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(tableId);

        // 获取默认数据源
        BaseDataSource defaultDataSource = this.commonService.getDefaultDataSource();

        // 获取默认DB Adapter
        DbAdapter dbAdapter = this.commonService.getDefaultDbAdapter();

        // 获取查询SQL
        String querySql = this.commonService.getQuerySql(tableDTO.getTableName(), dataId, columnList);

        // 获取查询结果
        Map<String, Object> queryRet = new HashMap<>();
        queryRet.put("columnList", columnList);
        Map<String, Object> dataList = getDataFromDb(dbAdapter, defaultDataSource, querySql, 1, 1);
        queryRet.putAll(dataList);

        return queryRet;
    }

    /**
     * 查询数据列表
     *
     * @param topicId  主题ID
     * @param pageNo   页码
     * @param pageSize 分页大小
     * @return
     */
    public Map<String, Object> getDataList(String topicId, Integer pageNo, Integer pageSize) {
        if (StringUtils.isEmpty(topicId)) {
            logger.warn("模型ID为空");
            return new HashMap<>();
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableByTopicId(topicId);
        String tableId = tableDTO.getId();

        // 获取字段列表(业务字段、系统内置字段)
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(tableId);
        columnList.addAll(this.commonService.getDefaultColumns());

        // 获取默认数据源
        BaseDataSource defaultDataSource = this.commonService.getDefaultDataSource();

        // 获取默认DB Adapter
        DbAdapter dbAdapter = this.commonService.getDefaultDbAdapter();

        // 获取查询SQL
        String querySql = this.commonService.getQuerySql(tableDTO.getTableName(), null, columnList);

        // 获取查询结果
        Map<String, Object> queryRet = new HashMap<>();
        queryRet.put("columnList", columnList);
        Map<String, Object> dataList = getDataFromDb(dbAdapter, defaultDataSource, querySql, pageNo, pageSize);
        queryRet.putAll(dataList);

        // 设置创建人、数据状态，去掉不需要展示的字段信息
        valueConvert((List<Map<String, Object>>) queryRet.get("resultList"));

        return queryRet;
    }

    /**
     * 查询字段列表（新增数据时使用）
     *
     * @param topicId 主题ID
     * @return
     */
    public List<ColumnDTO> getColumnList(String topicId) {
        if (StringUtils.isEmpty(topicId)) {
            logger.warn("模型ID为空");
            return new ArrayList<>();
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableByTopicId(topicId);
        String tableId = tableDTO.getId();

        // 获取编码规则
        List<CodeDTO> codeList = this.commonService.getCodeListByCond(tableId);

        // 获取字段列表(仅包含业务字段，不包括系统内置字段)
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(tableId);

        // 填充字段编码，设置在defaultValue中
        setColumnDefaultValue(columnList, codeList);

        return columnList;
    }

    /**
     * 修订/生效/失效
     *
     * @param dataDTO
     * @return
     */
    @Transactional
    public boolean updateStatus(DataDTO dataDTO) {
        if (dataDTO == null) {
            throw new BusinessException("参数为空");
        }
        if (StringUtils.isEmpty(dataDTO.getTableId())) {
            throw new BusinessException("模型Id为空");
        }
        if (StringUtils.isEmpty(dataDTO.getDataId())) {
            throw new BusinessException("数据Id为空");
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableById(dataDTO.getTableId());
        if (tableDTO == null) {
            throw new BusinessException("未找到模型，修订数据失败,tableId:" + dataDTO.getTableId());
        }

        // 获取数据版本信息
        String oldVersion = getDataVersion(tableDTO, dataDTO);

        // 更新数据
        String sql = this.commonService.getUpdateStatusSql(tableDTO.getTableName(), dataDTO.getDataId(), dataDTO.getStatus(), oldVersion);
        this.commonService.updateTable(tableDTO.getTableName(), sql);

        // 记录审计日志
        this.mdmLogService.updateLog(dataDTO.getTableId(), dataDTO.getDataId(), dataDTO.getStatus(), null);

        return true;
    }

    /**
     * 从数据库查询数据
     *
     * @param adapter
     * @param datasource
     * @param querySql
     * @param pageNo
     * @param pageSize
     * @return
     */
    private Map<String, Object> getDataFromDb(DbAdapter adapter, BaseDataSource datasource, String querySql,
                                              Integer pageNo, Integer pageSize) {
        Map<String, Object> dataList = new HashMap<>();
        try {
            dataList = adapter.getTableDataListFromDb(datasource, querySql, pageNo, pageSize, null);
        } catch (Exception e) {
            throw new BusinessException("获取数据失败", e);
        }

        return dataList;
    }

    /**
     * 新增一条数据
     *
     * @param dataDTO
     * @param tableDTO
     * @param columnList
     * @return
     */
    private String addDataInner(DataDTO dataDTO, TableDTO tableDTO, List<ColumnDTO> columnList) {
        String dataId = ComUtil.getId();
        String insertSql = this.commonService.getInsertSql(tableDTO.getId(), dataId, tableDTO.getTableName(), dataDTO.getDataMap(), columnList);
        logger.info(insertSql);

        this.commonService.insertTable(tableDTO.getTableName(), insertSql);

        this.mdmLogService.addLog(dataDTO.getTableId(), dataId, DataState.EDIT.getCode(), null);

        // 向推送模块保存变更的主数据
        saveChangeData(dataDTO.getTableId(), dataId, OperType.INSERT.getCode());
        return dataId;
    }

    /**
     * 更新一条数据
     *
     * @param dataDTO
     * @param tableDTO
     * @param columnList
     * @return
     */
    private boolean updateDataInner(DataDTO dataDTO, TableDTO tableDTO, List<ColumnDTO> columnList) {
        String updateSql = this.commonService.getUpdateSql(dataDTO.getDataId(), tableDTO.getTableName(), dataDTO.getDataMap(), columnList);
        logger.info(updateSql);

        this.commonService.updateTable(tableDTO.getTableName(), updateSql);

        // 向推送模块保存变更的主数据
        saveChangeData(dataDTO.getTableId(), dataDTO.getDataId(), OperType.UPDATE.getCode());
        return true;
    }

    /**
     * 根据编码规则，设置字段默认值
     *
     * @param columnList
     * @param codeList
     */
    private void setColumnDefaultValue(List<ColumnDTO> columnList, List<CodeDTO> codeList) {
        if (CollectionUtils.isEmpty(codeList)) {
            return;
        }
        if (CollectionUtils.isEmpty(columnList)) {
            return;
        }

        Map<String, CodeDTO> codeMap = codeList.stream().collect(Collectors.toMap(CodeDTO::getColumnId, item -> item));
        try {
            for (ColumnDTO column : columnList) {
                String columnId = column.getId();
                CodeDTO code = codeMap.get(columnId);
                if (code == null) {
                    continue;
                }

                String codeValue = this.dataCodeService.produceCode(code.getRuleId(), column.getTableId(), column.getName(), new HashMap<>(), 1);
                column.setDefaultValueList(Arrays.asList(codeValue));
            }
        } catch (Exception e) {
            logger.error("设置编码失败，errMsg={}", e);
        }
    }

    /**
     * 获取数据版本
     *
     * @param dataDTO
     * @return
     */
    private String getDataVersion(TableDTO tableDTO, DataDTO dataDTO) {
        // 获取字段列表
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(tableDTO.getId());
        columnList.addAll(this.commonService.getDefaultColumns());

        // 获取默认数据源
        BaseDataSource defaultDataSource = this.commonService.getDefaultDataSource();

        // 获取默认DB Adapter
        DbAdapter dbAdapter = this.commonService.getDefaultDbAdapter();

        // 获取查询SQL
        String querySql = this.commonService.getQuerySql(tableDTO.getTableName(), dataDTO.getDataId(), columnList);

        // 获取查询结果
        Map<String, Object> queryRet = new HashMap<>();
        queryRet.put("columnList", columnList);
        Map<String, Object> dataList = getDataFromDb(dbAdapter, defaultDataSource, querySql, 1, 1);
        queryRet.putAll(dataList);

        if (queryRet.get("resultList") == null) {
            return null;
        }
        List<Map<String, Object>> resultList = (List<Map<String, Object>>) queryRet.get("resultList");
        if (CollectionUtils.isEmpty(resultList)) {
            return null;
        }

        Object oldVersion = resultList.get(0).get("sys_data_version");
        if (oldVersion != null) {
            return oldVersion.toString();
        }

        return null;
    }

    /**
     * 通过平台API将字段值转换为名称，包括通用选择组件、通用代码
     *
     * @param dataList
     */
    private void valueConvert(List<Map<String, Object>> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }

        // 设置创建者名称
        Map<String, Set<String>> convertFormData = new HashMap<>();
        for (Map<String, Object> data : dataList) {
            if (data == null) {
                continue;
            }

            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, data.get("sys_created_by").toString());
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, data.get("sys_last_updated_by").toString());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            for (Map<String, Object> data : dataList) {
                if (data == null) {
                    continue;
                }

                data.put("sys_created_by", BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, data.get("sys_created_by").toString()));
                data.put("sys_last_updated_by", BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, data.get("sys_last_updated_by").toString()));
            }
        }

        // 设置枚举值
        for (Map<String, Object> data : dataList) {
            if (data == null) {
                continue;
            }

            // 设置数据状态
            data.put("sys_status", DataState.getDescByCode(Integer.parseInt(data.get("sys_status").toString())));
        }
    }

    /**
     * 向推送模块保存变更的主数据
     */
    private void saveChangeData(String tableId, String dataId, int operType){
        Map<String, Object> map = getDataDetailById(tableId, dataId);
        if(map == null){
            return;
        }
        List<Map<String, Object>> resultList = (List<Map<String, Object>>) map.get("resultList");
        if (CollectionUtils.isNotEmpty(resultList)) {
            if(resultList.size() == 1){
                Map<String, Object> resultMap = resultList.get(0);
                String data = JSON.toJSONString(resultMap);
                mdataChangeService.saveChangeData(tableId, operType, data);
            }
        }
    }

    private Map<String, Object> getDataDetailById(String tableId, String dataId) {
        if (StringUtils.isEmpty(tableId)) {
            logger.error("模型Id为空");
            return null;
        }
        if (StringUtils.isEmpty(dataId)) {
            logger.error("数据Id为空");
            return null;
        }

        // 获取模型信息
        TableDTO tableDTO = this.commonService.getTableById(tableId);

        // 获取字段列表(业务字段、系统内置字段)
        List<ColumnDTO> columnList = this.commonService.getColumnListByTableId(tableId);
        columnList.addAll(this.commonService.getDefaultColumns());

        // 获取默认数据源
        BaseDataSource defaultDataSource = this.commonService.getDefaultDataSource();

        // 获取默认DB Adapter
        DbAdapter dbAdapter = this.commonService.getDefaultDbAdapter();

        // 获取查询SQL
        String querySql = this.commonService.getQuerySql(tableDTO.getTableName(), dataId, columnList);

        // 获取查询结果
        Map<String, Object> dataList = getDataFromDb(dbAdapter, defaultDataSource, querySql, 1, 1);
        return dataList;
    }

}
